#ifndef TestPrimes_h
#define TestPrimes_h

// --------
// includes
// --------

#include <sstream> // istringtstream, ostringstream
#include <string>  // ==

#include "cppunit/TestFixture.h"             // TestFixture
#include "cppunit/extensions/HelperMacros.h" // CPPUNIT_TEST, CPPUNIT_TEST_SUITE, CPPUNIT_TEST_SUITE_END

// ----------
// TestPrimes
// ----------

struct TestPrimes : CppUnit::TestFixture {
    // ----
    // read
    // ----

    void test_read () {
        std::istringstream in("24\n");
        const bool b = read(in);
        CPPUNIT_ASSERT(b == true);
        CPPUNIT_ASSERT(num == 24);}

    // ----
    // eval
    // ----

    void test_eval_1 () {
        num =  24;
        sum[0] = 0;
        sum[1] = 0;
        sum[2] = 0;
        sum[3] = 0;
        const bool b = eval();
        CPPUNIT_ASSERT(b == false);
	CPPUNIT_ASSERT(sum[0] == 2);
	CPPUNIT_ASSERT(sum[1] == 2);
	CPPUNIT_ASSERT(sum[2] == 3);
	CPPUNIT_ASSERT(sum[3] == 17);}

    void test_eval_2 () {
        num =  36;
        sum[0] = 0;
        sum[1] = 0;
        sum[2] = 0;
        sum[3] = 0;
        const bool b = eval();
        CPPUNIT_ASSERT(b == false);
	CPPUNIT_ASSERT(sum[0] == 2);
	CPPUNIT_ASSERT(sum[1] == 2);
	CPPUNIT_ASSERT(sum[2] == 3);
	CPPUNIT_ASSERT(sum[3] == 29);}

    void test_eval_3 () {
        num =  46;
        sum[0] = 0;
        sum[1] = 0;
        sum[2] = 0;
        sum[3] = 0;
        const bool b = eval();
        CPPUNIT_ASSERT(b == false);
	CPPUNIT_ASSERT(sum[0] == 2);
	CPPUNIT_ASSERT(sum[1] == 2);
	CPPUNIT_ASSERT(sum[2] == 5);
	CPPUNIT_ASSERT(sum[3] == 37);}

    void test_eval_4 () {
        num =  500;
        sum[0] = 0;
        sum[1] = 0;
        sum[2] = 0;
        sum[3] = 0;
        const bool b = eval();
        CPPUNIT_ASSERT(b == false);
	CPPUNIT_ASSERT(sum[0] == 2);
	CPPUNIT_ASSERT(sum[1] == 2);
	CPPUNIT_ASSERT(sum[2] == 5);
	CPPUNIT_ASSERT(sum[3] == 491);}

    void test_eval_5 () {
        num =  50000;
        sum[0] = 0;
        sum[1] = 0;
        sum[2] = 0;
        sum[3] = 0;
        const bool b = eval();
        CPPUNIT_ASSERT(b == false);
	CPPUNIT_ASSERT(sum[0] == 2);
	CPPUNIT_ASSERT(sum[1] == 2);
	CPPUNIT_ASSERT(sum[2] == 3);
	CPPUNIT_ASSERT(sum[3] == 49993);}

    void test_eval_6 () {
        num =  8;
        sum[0] = 0;
        sum[1] = 0;
        sum[2] = 0;
        sum[3] = 0;
        const bool b = eval();
        CPPUNIT_ASSERT(b == false);
	CPPUNIT_ASSERT(sum[0] == 2);
	CPPUNIT_ASSERT(sum[1] == 2);
	CPPUNIT_ASSERT(sum[2] == 2);
	CPPUNIT_ASSERT(sum[3] == 2);}

    void test_eval_7 () {
        num =  7;
        const bool b = eval();
        CPPUNIT_ASSERT(b == true);}

    // -----------
    // check_prime
    // -----------

    void test_check_prime_1 () {
	const bool b = check_prime(20);
	CPPUNIT_ASSERT(b == false);}

    void test_check_prime_2 () {
	const bool b = check_prime(19);
	CPPUNIT_ASSERT(b == true);}

    // -----
    // print
    // -----

    void test_print_1 () {
        sum[0] = 2;
        sum[1] = 2;
        sum[2] = 3;
	sum[3] = 17;
        std::ostringstream out;
        print(out, false);
        CPPUNIT_ASSERT(out.str() == "2 2 3 17\n");}

    void test_print_2 () {
        std::ostringstream out;
        print(out, true);
        CPPUNIT_ASSERT(out.str() == "Impossible.\n");}

    // -----
    // suite
    // -----

    CPPUNIT_TEST_SUITE(TestPrimes);

    CPPUNIT_TEST(test_read);

    CPPUNIT_TEST(test_eval_1);
    CPPUNIT_TEST(test_eval_2);
    CPPUNIT_TEST(test_eval_3);
    CPPUNIT_TEST(test_eval_4);
    CPPUNIT_TEST(test_eval_5);
    CPPUNIT_TEST(test_eval_6);
    CPPUNIT_TEST(test_eval_7);

    CPPUNIT_TEST(test_check_prime_1);
    CPPUNIT_TEST(test_check_prime_2);

    CPPUNIT_TEST(test_print_1);
    CPPUNIT_TEST(test_print_2);

    CPPUNIT_TEST_SUITE_END();};

#endif // TestPrimes_h

